/*
 * Copyright 2008 Wink Saville
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.saville.testclient;

import com.saville.debug.*;
import com.saville.msgcomp.*;
import com.saville.hmc.*;

public class TestClient extends ActiveHmc {
    public TestClient(String name) {
        super(name, 4, 1);
        df = Log.VERBOSE;

        Log.d(df, "%s: MyHsm() E id=%d", mName, mMcId.id);
        State_Default s = new State_Default();
        states[0] = s;
        states[1] = s.new State_Initial().setParent(0);
        states[2] = s.new State_WaitForConnection().setParent(0);
        states[3] = s.new State_Working().setParent(0);

        completeConstruction();
        Log.d(df, "TestClient: TestClient() X");
    }

    private class State_Default extends State {
        @Override
        public boolean doState(Msg msg) {
            Log.d(df, "%s: Default X", mName);
            Log.d(df, "%s: Default X", mName);
            return true;
        }

        private class State_Initial extends State {
            @Override
            public boolean doState(Msg msg) {
                if (msg.is(McConst.MC_GUID, McConst.MC_CMD_STARTED)) {
                    Log.d(df, "%s: State_Initial STARTED", mName);
                } else {
                    Log.d(df, "%s: got %d", mName, msg.cmd);
                }

                transitionTo(2);
                return true;
            }
        }

        private class State_WaitForConnection extends State {
            @Override
            public boolean doState(Msg msg) {

                Log.d(df, "%s: WaitForConnection E", mName);

                // Count, Server dstId and server command
                mCount = msg.arg1;
                mServerDstId = (int) msg.arg2;
                mServerGuid = 0;
                mServerCmd = (int) msg.arg3 | McConst.CMD_NEEDS_REPLY;
                mCurCount = 0;

                mStartTsc = Timing.readTsc();
                msg = getMsg(mServerDstId, mServerGuid, mServerCmd);
                sendMsg(msg);
                transitionTo(3);

                Log.d(df, "%s: WaitForConnection X", mName);
                return true;
            }
        }

        private class State_Working extends State {
            @Override
            public boolean doState(Msg msg) {
                if ((mServerCmd & McConst.NOISY) != 0)
                    Log.d(df, "%s: Working E mCurCount=%d mCount=%d",
                        mName, mCurCount, mCount);

                if (++mCurCount >= mCount) {
                    double dur = Timing.tscToSecs(Timing.readTsc() - mStartTsc);
                    Log.print("TestClient: Done %s dur=%8.6f rate=%7.3f/s",
                        mName, dur, (mCurCount * 2.0) / dur);
                    transitionTo(2);
                } else {
                    msg = getMsg(mServerDstId, mServerGuid, mServerCmd);
                    sendMsg(msg);
                }

                if ((mServerCmd & McConst.NOISY) != 0)
                    Log.d(df, "%s: State_Working X", mName);
                return true;
            }
        }
    }

    private long mStartTsc;
    private long mCount;
    private int mServerDstId;
    private int mServerCmd;
    private int mServerGuid;
    private long mCurCount;
}
